package com.sscl.easyble.advertise

import androidx.annotation.IntRange
import androidx.annotation.Size
import com.sscl.easyble.BleManager

/**
 * @author jackie
 */
class FixedAdvertiseData(
    @param:IntRange(
        from = 0,
        to = 0xFFFF
    ) val manufactureId: Int,
    @param:Size(min = 1, max = MAX_ADVERTISE_DATA_LENGTH) val data: ByteArray
) {
    override fun toString(): String {
        val result = getFullDataByteArray()
        return ("AdvertiseData{" +
                "manufacturerId=" + manufactureId +
                ", data=" + BleManager.byteArrayToHexStr(data) +
                '}') + "\nparse to hex bytes array:" + BleManager.byteArrayToHexStr(
            result
        )
    }

    constructor(@Size(min = 3, max = FULL_DATA_MAX_ADVERTISE_DATA_LENGTH) data: ByteArray) : this(
        getManufactureId(data),
        getManufactureData(data)
    )

    fun getFullDataByteArray(): ByteArray {
        val bytes: ByteArray = BleManager.intToByteArrayLength2(manufactureId)
        BleManager.revertData(bytes)
        val result = ByteArray(bytes.size + data.size)
        System.arraycopy(bytes, 0, result, 0, bytes.size)
        System.arraycopy(data, 0, result, bytes.size, data.size)
        return result
    }


    companion object {
        /**
         * The max data size to be advertised (27 bytes);
         * advertising data can't be more than 31 bytes ,but we only can use 29 bytes
         * start of 2 bytes is manufacturerId
         * then we can use 27 bytes for data( total 29 bytes)
         * for example: you want to advertise the data "01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29"
         * you shout set manufacturerId to "02 01"(for int value is 513,HEX vale 0x0201) and set data to "03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29"
         */
        private const val MAX_ADVERTISE_DATA_LENGTH = 29L

        private const val FULL_DATA_MAX_ADVERTISE_DATA_LENGTH = 31L

        private fun getManufactureData(data: ByteArray): ByteArray {
            val dataBytes = ByteArray(data.size - 2)
            System.arraycopy(data, 2, dataBytes, 0, dataBytes.size)
            return dataBytes
        }

        private fun getManufactureId(data: ByteArray): Int {
            val manufacturerByte = ByteArray(2)
            System.arraycopy(data, 0, manufacturerByte, 0, 2)
            BleManager.revertData(manufacturerByte)
            val manufacturerId = BleManager.byteArray2LengthToInt(manufacturerByte)
            return manufacturerId
        }
    }
}
